package com.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;

import com.dao.BaseDao;
import com.dto.Pageinfo;
import com.dto.Pagers;

public class BaseDaoImpl<T> implements BaseDao<T> {

    protected Class<?> tclass;

    public BaseDaoImpl() {
	ParameterizedType type = (ParameterizedType) this.getClass()
		.getGenericSuperclass();
	System.out.println(type.getActualTypeArguments()[0]);
	tclass = (Class<?>) type.getActualTypeArguments()[0];
    }

    @Resource(name = "sessionFactory")
    private SessionFactory sessionFactory;

    public Session getSession() {
	return sessionFactory.getCurrentSession();
    }

    @Override
    public void save(T entity) {
	// TODO Auto-generated method stub
	getSession().save(entity);
    }

    @Override
    public void del(T entity) {
	// TODO Auto-generated method stub
	getSession().delete(entity);
    }

    @Override
    public void update(T entity) {
	// TODO Auto-generated method stub
	getSession().update(entity);
    }

    @SuppressWarnings("unchecked")
    @Override
    public T findById(int id) {
	// TODO Auto-generated method stub
	return (T) getSession().get(tclass, id);
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<T> findAll(Criterion... pamas) {
	// TODO Auto-generated method stub
	Criteria criteria = getSession().createCriteria(tclass);
	// Criterion criterion= Restrictions.eq("", "");
	if (pamas != null) {
	    for (Criterion criterion : pamas) {
		criteria.add(criterion);
	    }
	}
	return criteria.list();
    }

    @Override
    public int getCount() {
	// TODO Auto-generated method stub
	Query query = this.getSession().createQuery(
		"select count(*) from " + tclass.getName());
	return ((Integer) query.uniqueResult()).intValue();
    }

    @Override
    public Pagers getForPage(Pageinfo pageinfo, Criterion... pamas) {
	// TODO Auto-generated method stub
	Criteria criteria = this.getSession().createCriteria(tclass);
	if (pamas != null) {
	    for (Criterion criterion : pamas) {
		criteria.add(criterion);
	    }
	}
	int count = ((Number) criteria.setProjection(Projections.rowCount())
		.uniqueResult()).intValue();
	criteria.setProjection(null);
	String order = pageinfo.getOrder();
	String sort = pageinfo.getSort();
	if (sort != null) {
	    if (order != null && order.equals("esc")) {
		criteria.addOrder(Order.asc(pageinfo.getSort()));
	    } else {
		criteria.addOrder(Order.desc(pageinfo.getSort()));
	    }
	}
	criteria.setFirstResult((pageinfo.getPage() - 1) * pageinfo.getRows());
	criteria.setMaxResults(pageinfo.getRows());
	Pagers pager = new Pagers();
	List<?> list = criteria.list();
	pager.setRows(list);
	pager.setTotal(count);
	return pager;
    }

    @Override
    public List<T> getForPageList(Pageinfo pageinfo, Criterion... pamas) {
	// TODO Auto-generated method stub
	Criteria criteria = this.getSession().createCriteria(tclass);
	if (pamas != null) {
	    for (Criterion criterion : pamas) {
		criteria.add(criterion);
	    }
	}
	String order = pageinfo.getOrder();
	String sort = pageinfo.getSort();
	if (sort != null) {
	    if (order != null && order.equals("esc")) {
		criteria.addOrder(Order.asc(pageinfo.getSort()));
	    } else {
		criteria.addOrder(Order.desc(pageinfo.getSort()));
	    }
	}
	criteria.setFirstResult((pageinfo.getPage() - 1) * pageinfo.getRows());
	criteria.setMaxResults(pageinfo.getRows());
	return criteria.list();
    }

    @SuppressWarnings("unchecked")
    @Override
    public T Quary(String hql, Object... params) {
	// TODO Auto-generated method stub
	Query query = getSession().createQuery(hql);
	setPamas(query, params);
	return (T) query.uniqueResult();
    }

    public void setPamas(Query query, Object... params) {
	if (params != null) {
	    for (int i = 0; i < params.length; i++) {
		query.setParameter(i, params[i]);
	    }
	}
    }

    @Override
    public List<T> QuaryAll(String hql, Object... pamas) {
	// TODO Auto-generated method stub
	Query query = getSession().createQuery(hql);
	setPamas(query, pamas);

	return query.list();
    }

    @Override
    public int getCount(Criterion... pamas) {
	// TODO Auto-generated method stub
	Criteria criteria = getSession().createCriteria(tclass);
	// Criterion criterion= Restrictions.eq("", "");
	for (Criterion criterion : pamas) {
	    criteria.add(criterion);
	}
	criteria.setProjection(Projections.rowCount());
	Integer count = ((Number) (criteria).uniqueResult()).intValue();
	// System.out.println("--------------");
	// System.out.println(count);
	// System.out.println("--------------");
	return count;
    }

    @Override
    public void DelById(Integer id) {
	// TODO Auto-generated method stub
	this.getSession()
		.createQuery("delete from " + tclass.getName() + " where id=?")
		.setInteger(0, id).executeUpdate();
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<T> getByRond(int limit) {
	// TODO Auto-generated method stub;
	List<T> list = getSession()
		.createQuery(
			"from " + tclass.getName()
				+ " order by rand() limit 0,?")
		.setInteger(0, limit).list();
	return list;
    }

    @SuppressWarnings("unchecked")
    @Override
    public T getLast() {
	// TODO Auto-generated method stub
	Query query = this.getSession().createQuery(
		("from " + tclass.getName() + " order by id desc"));
	query.setFirstResult(0);
	query.setMaxResults(1);
	return (T) query.uniqueResult();

    }

    @SuppressWarnings("unchecked")
    @Override
    public List<T> getList(Order order, int start, int limit) {
	// TODO Auto-generated method stub
	Criteria criteria = this.getSession().createCriteria(tclass);
	criteria.addOrder(order);
	criteria.setFirstResult(start);
	criteria.setMaxResults(limit);
	return criteria.list();
    }

    @Override
    public void DelByStringids(String ids) {
	// TODO Auto-generated method stub
	String[] id = ids.split(",");
	for (String string : id) {
	    DelById(Integer.parseInt(string));
	}
    }

    @Override
    public void DelByIntids(Integer[] ids) {
	// TODO Auto-generated method stub
	Query query = this.getSession().createQuery(
		"delete from " + tclass.getName() + " where id in(:ids)");
	query.setParameterList("ids", ids);
	query.executeUpdate();
    }

    @Override
    public Query getQuery(String hql, Object... params) {
	// TODO Auto-generated method stub
	Query query = this.getSession().createQuery(hql);
	setPamas(query, params);
	return query;
    }

}
